package services.intermediate

import models.baseinfo.{GYItemCode, GYItemCodeRepository, CustomerCode, KDCustomerCodeRepository, KDStockCode, KDStockCodeRepository}
import models.users.KingdeeUser

import javax.inject.Inject
import play.api.Logging
import play.api.libs.json.{JsArray, JsObject, Json}
import security.Checked
import services.gyerpapi.GYCErpPost
import services.kingdee.{KingdeeConfig, KingdeePostV1}

import java.sql.Timestamp
import java.time.{LocalDate, LocalDateTime}
import java.time.format.DateTimeFormatter
import scala.collection.mutable
import scala.concurrent.duration.Duration
import scala.concurrent.{Await, ExecutionContext}

class BaseInfoUpdate @Inject()(
                                itemCodeRepo: GYItemCodeRepository,
                                stockCodeRepo: KDStockCodeRepository,
                                customerCodeRepo: KDCustomerCodeRepository,
                                kdPost: KingdeePostV1,
                                gyPost: GYCErpPost
                              )(implicit exec: ExecutionContext)
  extends Logging {


  //# 金蝶仓库代码
  private def getKdStockCode(date: String = "") = {
    val limit = 2000
    val lst: mutable.ArrayBuffer[KDStockCode] = mutable.ArrayBuffer()
    var isEnd = true
    val qs = if (date == "") {
      val d = LocalDateTime.now().minusDays(1).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))
      s"FAuditDate >= to_date('$d','yyyymmdd')"
    } else if (date.length == 8) {
      s"FAuditDate >= to_date('$date','yyyymmdd')"
    } else {
      ""
    }
    while (isEnd) {
      //# 取金蝶仓库信息
      val para_list = Json.obj(
        "FormId" -> "BD_STOCK",
        "FieldKeys" -> "FStockId,FNumber,FName,FGYStockNumber,FModifyDate,FUseOrgId.FNumber,FTHIRDSTOCKNO",
        "FilterString" -> qs, //# "FStockId=755915",
        "OrderString" -> "",
        "TopRowCount" -> 0,
        "StartRow" -> lst.size,
        "Limit" -> limit
      )
      //# Response = [[2004148, "W02109", "武汉聚信云仓", "800000105"], [2057144, "W02111", "嘉美小件仓", "W02111"], [2059604, "W02112", "晋江中通云仓", "595-003C"]]  #
      val res = Await.result(kdPost.post(kdPost.kingdeePostApi("Query"), parameters = Json.arr(para_list)), Duration.Inf)
      val arr = Json.parse(res).as[Array[JsArray]].map(
        f => KDStockCode(
          id = f.value(0).as[Int] * 10 + 1,
          kdFStockId = f.value(0).as[Int],
          kdFNumber = f.value(1).as[String],
          kdFName = f.value(2).as[String],
          kdFTHIRDSTOCKNO = f.value(3).as[String],
          org = f.value(5).as[String],
          upDate = Timestamp.valueOf("T".r.replaceFirstIn(f.value(4).as[String], " "))
        )
      )
      isEnd = arr.length != 0
      for (f <- arr) {
        lst.append(f)
        if (System.currentTimeMillis() - f.upDate.getTime < 86400_000 * 30) true
          stockCodeRepo.insert(f)
      }
    }
    lst
  }

  private def getKdMaterial(date: String = "") = {
    val limit = 2000
    val lst: mutable.ArrayBuffer[GYItemCode] = mutable.ArrayBuffer()
    var isEnd = true
    val qs = if (date == "") {
      val d = LocalDateTime.now().minusDays(1).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))
      s"FCreateOrgId.FNumber='100' and FApproveDate >= to_date('$d','yyyymmdd')"
    } else if (date.length == 8) {
      s"FCreateOrgId.FNumber='100' and FApproveDate >= to_date('$date','yyyymmdd')"
    } else {
      "FCreateOrgId.FNumber='100'"
    }
    while (isEnd) {
      //# 取金蝶物料信息
      val para_list = Json.obj(
        "FormId" -> "BD_MATERIAL",
        "FieldKeys" -> "FMaterialId,FNumber,FName,FBARCODE,FBaseUnitId.FNumber,FSaleUnitId.FNumber,FModifyDate,FErpClsID,FGROSSWEIGHT,FWEIGHTUNITID.fnumber,FLENGTH,FWIDTH,FHEIGHT,FVOLUME,FVOLUMEUNITID.fnumber",
        "FilterString" -> qs, //#"FMaterialId=829430",   # sql条件
        "OrderString" -> "",
        "TopRowCount" -> 0,
        "StartRow" -> lst.size,
        "Limit" -> limit
      )
      //# Response = [[829430, "F03010011", "测试产品1", " "],[829430, "F03010011", "测试产品1", " "]]  #
      val res = Await.result(kdPost.post(kdPost.kingdeePostApi("Query"), parameters = Json.arr(para_list)), Duration.Inf)
      logger.debug(res)
      val arr = Json.parse(res)
        .as[Array[JsArray]]
        .map(f =>
          GYItemCode(
            id = f.value(0).as[Int] * 10 + 1,
            kdMaterialId = f.value(0).as[Int],
            kdNumber = f.value(1).as[String],
            kdFName = f.value(2).as[String],
            kdBarcode = f.value(3).asOpt[String].getOrElse(""),
            kdBaseUnit = f.value(4).as[String],
            kdErpClsId = f.value(7).as[String],
            kdWeight = f.value(8).as[Double],
            kdWeightUnit = f.value(9).as[String].take(2),
            kdLength = f.value(10).as[Double],
            kdWidth = f.value(11).as[Double],
            kdHeight = f.value(12).as[Double],
            kdVolume = f.value(13).as[Double],
            kdVolumeUnit = f.value(14).as[String],
            upDate = Timestamp.valueOf("T".r.replaceFirstIn(f.value(6).as[String], " ")),
            gyCode = f.value(1).as[String],
            gyName = f.value(2).as[String],
            gyBarcode = f.value(3).asOpt[String].getOrElse("")
          ))
      isEnd = arr.length != 0
      for (f <- arr) {
        val w = f.kdWeightUnit match {
          // case "kg"=> f.copy()
          case "g"=>f.copy(kdWeight = f.kdWeight/1000.0,kdWeightUnit = "kg")
          case "to"=>f.copy(kdWeight = f.kdWeight*1000,kdWeightUnit = "kg")
          case _ =>f.copy(kdWeightUnit = f.kdWeightUnit.take(2))
        }
        val v = w.kdVolumeUnit match {
          case "mm" =>w.copy(kdWidth = w.kdWidth/10.0,kdLength = w.kdLength/10.0,kdHeight = w.kdHeight/10.0,kdVolume=w.kdVolume/1000.0,kdVolumeUnit = "cm" )
          case "m" => w.copy(kdWidth = w.kdWidth*100.0,kdLength = w.kdLength*100.0,kdHeight = w.kdHeight*100.0,kdVolume=w.kdVolume*1000000.0,kdVolumeUnit = "cm")
          case _ => w.copy(kdVolumeUnit = w.kdVolumeUnit.take(2))
        }
        lst.append(f)
        if (System.currentTimeMillis() - f.upDate.getTime < 86400_000 * 30 || true) itemCodeRepo.insert(v)
      }
      logger.debug(lst.length.toString)
    }
    logger.debug(lst.length.toString)
    lst
  }

  private def getKdCustomer(date: String = "111") = {
    val limit = 2000
    val lst: mutable.ArrayBuffer[CustomerCode] = mutable.ArrayBuffer()
    var isEnd = true
    val qs = if (date == "") {
      val d = LocalDateTime.now().minusDays(1).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))
      s"FCreateOrgId.FNumber='100' and FApproveDate >= to_date('$d','yyyymmdd')"
    } else if (date.length == 8) {
      s"FCreateOrgId.FNumber='100' and FApproveDate >= to_date('$date','yyyymmdd')"
    } else {
      "FCreateOrgId.FNumber='100'"
    }
    while (isEnd) {
      //# 取金蝶客户信息
      val para_list = Json.obj(
        "FormId" -> "BD_Customer",
        "FieldKeys" -> "FCUSTID,FNumber,FName,FCreateOrgId.fnumber,FModifyDate,F_PAEZ_Assistant.fnumber",
        "FilterString" -> qs, //#"FMaterialId=829430",   # sql条件
        "OrderString" -> "",
        "TopRowCount" -> 0,
        "StartRow" -> lst.size,
        "Limit" -> limit
      )
      //# Response = [[829430, "F03010011", "测试产品1", " "],[829430, "F03010011", "测试产品1", " "]]  #
      val res = Await.result(kdPost.post(kdPost.kingdeePostApi("Query"), parameters = Json.arr(para_list)), Duration.Inf)
//      logger.debug(res)
      val arr = Json.parse(res)
        .as[Array[JsArray]]
        .map(f =>
          CustomerCode(
            kdId = f.value(0).as[Int],
            kdNo = f.value(1).as[String],
            kdName = f.value(2).as[String],
            org = f.value(5).as[String],
            upDate = Timestamp.valueOf("T".r.replaceFirstIn(f.value(4).as[String], " "))
          ))
      isEnd = arr.length != 0
      for (f <- arr) {
        lst.append(f)
        //        if (System.currentTimeMillis() - f.upDate.getTime < 86400_000 * 30 && true) customerCodeRepo.insertKdInfo(f)
      }
      logger.debug(lst.length.toString)
    }
    logger.debug(lst.length.toString)
    lst
  }

  private def getGyShopCode() = {
    val limit = 100
    var page = 1
    var total = 1
    val lst: mutable.ArrayBuffer[CustomerCode] = mutable.ArrayBuffer()
    val date = LocalDate.now()
    val start_date = date.plusDays(-30).format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) + " 00:00:00"
    val end_date = date.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) + " 00:00:00"
    while (page <= total) {
      val para_list = Json.obj(
        "method" -> "gy.erp.shop.get",
        "page_no" -> page,
        "page_size" -> limit,
        //"start_date" -> start_date,
        //"end_date" -> end_date
      )
      val res = Await.result(gyPost.post(para_list), Duration.Inf)
      if ((res \ "success").as[Boolean]) {
        val a = (res \ "total").as[Int] / limit + 1
        if (a > total) total = a
        val arr = (res \ "shops").as[Array[JsObject]].map { r =>
          (
            Checked.asString(r("id")).toLong,
            r("code").as[String],
            r("name").as[String],
            r("modify_date").as[String]
          )
        }
        for (f <- arr) {
          lst.append(CustomerCode(id = f._1, code = f._2, name = f._3, upDate = Timestamp.valueOf(f._4)))
          //          customerCodeRepo.insert(KDCustomerCode(id=f._1,code = f._2,name = f._3))
        }
      } else {
        logger.debug(res.toString())
        page = total + 1
      }
      logger.debug(s"total=$total,page=$page")
      page += 1
    }
    lst
  }

  def getCustomerCode1() = {
    val gyShops = getGyShopCode()
    logger.debug(s"gyShops = ${gyShops.length}")
    val kdCustomers = getKdCustomer()
    logger.debug(s"kdCustomers = ${kdCustomers.mkString(",")}")
    val lst: mutable.ArrayBuffer[CustomerCode] = mutable.ArrayBuffer()
    for (v <- gyShops) {
      val shopcode = v.code.split("-")(0)
      val kd = kdCustomers.filter(_.kdNo == shopcode)
      if (kd.nonEmpty) {
        val k = kd.head
        v.kdId = k.kdId
        v.kdNo = k.kdNo
        v.kdName = k.kdName
        v.org = k.org
        v.upDate = k.upDate
      }
      lst.append(v)
    }
    logger.debug(s"gyShops List = ${lst.mkString(",")}")
    lst.map(r => customerCodeRepo.insert(r))
    customerCodeRepo.list.map {
      seq => {
        for (customer <- seq) {
          kdCustomers.filter(f => f.kdId == customer.kdId && f.upDate.getTime > customer.upDate.getTime).map {
            r => {
              logger.debug(s"customerCodeRepo.updateKdInfo($r)")
              customerCodeRepo.updateKdInfo(r)
            }
          }
        }
      }
    }
  }

  def getCustomerCode() = {
//    val gyShops = getGyShopCode()
    val kdCustomers = getKdCustomer()
    val gyShops = kdCustomers.map(f=>f.copy(id=f.kdId,code=f.kdNo,name = f.kdName))
    logger.debug(s"gyShops = ${gyShops.length}")

    logger.debug(s"kdCustomers = ${kdCustomers.mkString(",")}")
    val lst: mutable.ArrayBuffer[CustomerCode] = mutable.ArrayBuffer()
    for (v <- gyShops) {
      val shopcode = v.code.split("-")(0)
      val kd = kdCustomers.filter(_.kdNo == shopcode)
      if (kd.nonEmpty) {
        val k = kd.head
        v.kdId = k.kdId
        v.kdNo = k.kdNo
        v.kdName = k.kdName
        v.org = k.org
        v.upDate = k.upDate
      }
      lst.append(v)
    }
    logger.debug(s"gyShops List = ${lst.mkString(",")}")
    lst.map(r => customerCodeRepo.insert(r))
    customerCodeRepo.list.map {
      seq => {
        for (customer <- seq) {
          kdCustomers.filter(f => f.kdId == customer.kdId && f.upDate.getTime > customer.upDate.getTime).map {
            r => {
              logger.debug(s"customerCodeRepo.updateKdInfo($r)")
              customerCodeRepo.updateKdInfo(r)
            }
          }
        }
      }
    }
  }

  private def updateGyItemCode(gyItemId: Long,
                               gyCode: String,
                               gyBarcode: String,
                               gyName: String,
                               status: Boolean = false) = {
    itemCodeRepo.update(gyItemId = gyItemId, gyCode = gyCode, gyName = gyName, gyBarcode = gyBarcode, status = status)
  }

  // 管易商品代码
  private def getGyItemCode() = {
    val limit = 100
    var page = 1
    var total = 1
    val lst: mutable.ArrayBuffer[(Long, String, String, Boolean)] = mutable.ArrayBuffer()
    val date = LocalDate.now()
    val start_date = date.plusDays(-30).format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) + " 00:00:00"
    val end_date = date.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) + " 00:00:00"
    while (page <= total) {
      val para_list = Json.obj(
        "method" -> "gy.erp.items.get",
        "page_no" -> page,
        "page_size" -> limit,
        "start_date" -> start_date,
        "end_date" -> end_date
      )
      val res = Await.result(gyPost.post(para_list), Duration.Inf)
      if ((res \ "success").as[Boolean]) {
        val a = (res \ "total").as[Int] / limit + 1
        if (a > total) total = a
        val arr = (res \ "items").as[Array[JsObject]].map { r =>
          (
            Checked.asString(r("id")).toLong,
            r("code").as[String],
            r("name").as[String],
            r("del").as[Boolean]
          )
        }
        for (f <- arr) {
          lst.append(f)
        }
      } else {
        logger.debug(res.toString())
        page = total + 1
      }
      logger.debug(s"total=$total,page=$page")
      page += 1
    }
    lst.map(r => updateGyItemCode(gyItemId = r._1, gyCode = r._2, gyName = r._3, status = r._4, gyBarcode = ""))
    lst
  }

  // 管易商品条码
  private def getGyBarCode() =  mutable.ArrayBuffer[(Long, String, String, String, Boolean)]()
  private def getGyBarCode1() = {
    val limit = 100
    var page = 1
    var total = 1
    val lst: mutable.ArrayBuffer[(Long, String, String, String, Boolean)] = mutable.ArrayBuffer()
    val date = LocalDate.now()
    val start_date = date.plusDays(-30).format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) + " 00:00:00"
    val end_date = date.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) + " 00:00:00"
    while (page <= total) {
      val para_list = Json.obj(
        "method" -> "gy.erp.item.barcode.get",
        "page_no" -> page,
        "page_size" -> limit,
        "start_date" -> start_date,
        "end_date" -> end_date,
        "date_type" -> 1
      )
      val res = Await.result(gyPost.post(para_list), Duration.Inf)
      if ((res \ "success").as[Boolean]) {
        val a = (res \ "total").as[Int] / limit + 1
        if (a > total) total = a
        val arr = (res \ "barcode").as[Array[JsObject]].map { r =>
          (
            Checked.asString(r("item_id")).toLong,
            r("item_code").as[String],
            r("item_name").as[String],
            r("barcode").as[String],
            r("is_del").as[Boolean]
          )
        }
        for (f <- arr) {
          lst.append(f)
        }
      } else {
        logger.debug(res.toString())
        page = total + 1
      }
      logger.debug(s"total=$total,page=$page")
      page += 1
    }
    lst.map(r => updateGyItemCode(gyItemId = r._1, gyCode = r._2, gyName = r._3, status = !r._5, gyBarcode = r._4))
    lst
  }


  def sameCodeUpdate() = {
    val kdStockCode = getKdStockCode()
    val kdMaterial = getKdMaterial()
    val gyBarCode = getGyBarCode()
    getCustomerCode()
    s"getKdStockCode()=${kdStockCode.length},getKdMaterial()=${kdMaterial.length},getGyBarCode()=${gyBarCode.length}"
  }

  def getKdAccount(kddc: KingdeeConfig) = {
    val limit = 2000
    val lst: mutable.ArrayBuffer[KingdeeUser] = mutable.ArrayBuffer()
    var isEnd = true
    while (isEnd) {
      //# 取金蝶商品信息
      //      实体主键：FUserID
      //      用户说明：FDescription
      //      用户名称：FName  (必填项)
      //      禁用状态：FForbidStatus
      //      部门分组：FPRIMARYGROUP
      //      创建日期：FCreateDate
      //      创建人：FCreatorId
      //      联系对象：FLinkObject
      //      密码：FPassword
      //      创建组织：FOrgId
      //      密码加密的Salt：FSalt
      //      锁定状态：FIsLock
      //      云之家帐号：FMBACCONT
      //      云之家注册状态：FRegState
      //      AccessToken：FAccessToken
      //      TokenSecret：FTokenSecret
      //      微博用户ID：FWeiboUserId
      //      用户帐号：FUserAccount
      //      域用户：FDomainUser
      //      联系对象类型：FType
      //      用户类型：FUserType
      //      邮箱：FEmail
      //      动态密码卡：FDynamicPassword
      //      移动电话：FPhone
      //      其它账号：FSocialId
      //      反禁用人：FEnableUserId
      //      反禁用日期：FEnableTime
      //      禁用人：FDisableUserId
      //      禁用日期：FDisableTime
      //      许可分组：FAppGroup
      //      云通行证ID：FKdPassportId
      val para_list = Json.obj(
        "FormId" -> "SEC_User",
        "FieldKeys" -> "FUserID,FName,FForbidStatus,FPhone,FDisableTime,FAppGroup",
        "FilterString" -> "", //#"FMaterialId=829430",   # sql条件
        "OrderString" -> "",
        "TopRowCount" -> 0,
        "StartRow" -> lst.size,
        "Limit" -> limit
      )
      //# Response = [2921912,"潘XX","B","13900000001","2021-04-12T09:15:34"," "],[3277677,"赵XX","A","13900000002",null,"Pro"]]  #
      val res = kdPost.post(kdPost.kingdeePostApi("Query"), parameters = Json.arr(para_list))
      res.map(r => {
        val arr = Json.parse(r).as[Array[JsArray]]
        isEnd = arr.length != 0
        arr.foreach(f =>
          lst.appended(
            KingdeeUser(
              id = f.value(0).as[Int],
              acct_id = kddc.dCID,
              name = f.value(1).as[String],
              mobile = f.value(3).as[String],
              forbid_status = f.value(2).as[String],
              disable_time = Option(Timestamp.valueOf(f.value(4).as[String])),
              fAppGroup = f.value(5).as[String]
            ))
        )
      })
    }
    lst
  }

}
